/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef RS_VULKAN_CONTEXT_CLIENT_H
#define RS_VULKAN_CONTEXT_CLIENT_H

#include <list>
#include <memory>
#include <mutex>
#include <string>
#include "image/gpu_context.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/vk/GrVkBackendContext.h"
#include "include/gpu/vk/GrVkExtensions.h"
#include "rs_vulkan_context.h"
#include "rs_vulkan_mem_statistic.h"
#include "sync_fence.h"
#include "vulkan/vulkan_core.h"
#include "vulkan/vulkan_xeg.h"
#include "vulkan/vulkan.h"

namespace OHOS {
namespace Rosen {
class MemoryHandler;
class RsVulkanContextClient {
public:
    static RsVulkanContextClient& GetSingleton();
    RsVulkanContextClient();
    ~RsVulkanContextClient() {};

    RsVulkanContextClient(const RsVulkanContextClient&) = delete;
    RsVulkanContextClient &operator=(const RsVulkanContextClient&) = delete;

    RsVulkanContextClient(const RsVulkanContextClient&&) = delete;
    RsVulkanContextClient &operator=(const RsVulkanContextClient&&) = delete;

    RsVulkanInterface& GetRsVulkanInterface();

    bool IsValid()
    {
        return GetRsVulkanInterface().IsValid();
    }

    GrVkGetProc CreateSkiaGetProc()
    {
        return GetRsVulkanInterface().CreateSkiaGetProc();
    }

    RsVulkanMemStat& GetRsVkMemStat()
    {
        return GetRsVulkanInterface().GetRsVkMemStat();
    }

    VkPhysicalDevice GetPhysicalDevice()
    {
        return GetRsVulkanInterface().GetPhysicalDevice();
    }

    VkDevice GetDevice()
    {
        return GetRsVulkanInterface().GetDevice();
    }

    VkQueue GetQueue()
    {
        return GetRsVulkanInterface().GetQueue();
    }

    inline const GrVkBackendContext& GetGrVkBackendContext(
        bool useHBackendContext = false) noexcept
    {
        return GetRsVulkanInterface().GetGrVkBackendContext(useHBackendContext);
    }

    inline const std::string GetVulkanVersion()
    {
        return std::to_string(VK_API_VERSION_1_2);
    }

    std::shared_ptr<Drawing::GPUContext> CreateDrawingContext(bool independentContext = false);
    std::shared_ptr<Drawing::GPUContext> GetDrawingContext();

    void ClearGrContext();

    static VKAPI_ATTR VkResult HookedVkQueueSubmit(VkQueue queue, uint32_t submitCount,
        VkSubmitInfo* pSubmits, VkFence fence);

    static VKAPI_ATTR VkResult HookedVkQueueSignalReleaseImageOHOS(VkQueue queue, uint32_t waitSemaphoreCount,
        const VkSemaphore* pWaitSemaphores, VkImage image, int32_t* pNativeFenceFd);

    std::shared_ptr<Drawing::GPUContext> GetHardWareGrContext()
    {
        return GetRsVulkanInterface().GetHardWareGrContext();
    }

    VkQueue GetHardwareQueue()
    {
        return GetRsVulkanInterface().GetHardwareQueue();
    }

    const std::shared_ptr<MemoryHandler> GetMemoryHandler()
    {
        return GetRsVulkanInterface().GetMemoryHandler();
    }

private:
    static thread_local std::shared_ptr<Drawing::GPUContext> drawingContextClient_;
    RsVulkanInterface rsVulkanInterface_;
};

} // namespace Rosen
} // namespace OHOS

#endif
